package com.notary.tx_live_plugin.util;

import android.util.Log;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;

public final class TxLogger {

    public static final int VERBOSE = Log.VERBOSE;
    public static final int DEBUG = Log.DEBUG;
    public static final int INFO = Log.INFO;
    public static final int WARN = Log.WARN;
    public static final int ERROR = Log.ERROR;
    public static final int ASSERT = Log.ASSERT;

    private static final String ClassName = TxLogger.class.getName();

    /* 允许输出的日志级别 */
    private static int LEVEL = VERBOSE;
    /* 日志输出TAG */
    private static String TAG = "TxLogger";

    /**
     * 设置日志输出级别,低于该{@code level}的日志信息将不会显示在 logcat中
     * @param level 显示级别从低到高依次为
     * <ol>
     * <li>{@link #VERBOSE}</li>
     * <li>{@link #DEBUG}</li>
     * <li>{@link #INFO}</li>
     * <li>{@link #WARN}</li>
     * <li>{@link #ERROR}</li>
     * <li>{@link #ASSERT}</li>
     * </ol>
     * 默认日志级别为最低的{@link #VERBOSE}
     */
    public static void setLogLevel(int level){
        LEVEL = level;
    }
    /**
     * 设置日志输出TAG
     * @param tag TAG
     */
    public static void setTag(String tag) {
        TAG = tag;
    }

    public static <T> void v(T msg){
        printLog(VERBOSE,msg);
    }

    public static <T> void d(T msg){
        printLog(DEBUG,msg);
    }

    public static <T> void i(T msg){
        printLog(INFO,msg);
    }

    public static <T> void w(T msg){
        printLog(WARN,msg);
    }

    public static <T> void e(T msg){
        printLog(ERROR,msg);
    }

    public static void v(Object... msg){
        printLog(VERBOSE,msg);
    }

    public static void d(Object... msg){
        printLog(DEBUG,msg);
    }

    public static void i(Object... msg){
        printLog(INFO,msg);
    }

    public static void w(Object... msg){
        printLog(WARN,msg);
    }

    public static void e(Object... msg){
        printLog(ERROR,msg);
    }

    private static void printLog(int p, Object... msg) {
        if(isLoggable(p) == false) return;
        if(msg == null) return;

        StringBuilder sb = new StringBuilder();

        StackTraceElement[] statck = Thread.currentThread().getStackTrace();
        if(statck != null) {
            boolean isOk = false;
            for(StackTraceElement element : statck) {
                if(ClassName.equals(element.getClassName())) {
                    isOk = true;
                } else if(isOk) {
                    sb.append('[').append(element.getClassName()).append(':').append(':')
                            .append(element.getMethodName()).append('(')
                            .append(element.getLineNumber()).append(')').append(']');
                    break;
                }
            }
        }

        for(Object obj : msg) {
            if(obj == null) continue;

            sb.append(" ");
            if(obj instanceof Throwable) {
                sb.append(getStackTraceString((Throwable) obj));
            } else if(obj.getClass().isArray()) {
                int size = Array.getLength(obj);
                sb.append('[');
                for(int i = 0;i < size;i++ ) {
                    sb.append(Array.get(obj, i)).append(',');
                }
                sb.deleteCharAt(sb.length() - 1);
                sb.append(']');
            } else {
                sb.append(obj);
            }
        }
        showLongString(p, TAG, sb);
    }

    private static boolean isLoggable(int level) {
        return level >= LEVEL;
    }

    public static String getStackTraceString(Throwable tr) {
//		return Log.getStackTraceString(tr);
        if (tr == null) {
            return "";
        }
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        tr.printStackTrace(pw);
        pw.flush();
        return sw.toString();
    }

    public static void longV(String tag, CharSequence sequence){
        showLongString(VERBOSE, tag, sequence);
    }

    public static void longD(String tag, CharSequence sequence){
        showLongString(DEBUG, tag, sequence);
    }

    public static void longI(String tag, CharSequence sequence){
        showLongString(INFO, tag, sequence);
    }

    public static void longW(String tag, CharSequence sequence){
        showLongString(WARN, tag, sequence);
    }

    public static void longE(String tag, CharSequence sequence){
        showLongString(ERROR, tag, sequence);
    }

    /**
     * 打印超过LOGCAT设置的长度文本内容
     * @param p {@link #VERBOSE},{@link #DEBUG},{@link #INFO},{@link #WARN},{@link #ERROR},{@link #ASSERT}
     * @param tag TAG
     * @param sequence output string
     */
    public static void showLongString(int p, String tag, CharSequence sequence) {
        if(isLoggable(p) == false) return;
        String string = sequence.toString();

        int i = 0, size = string.length();
        while(true) {
            if(i > 0) tag = null;

            if(size >= 3000) {
                Log.println(p, tag, string.substring(i, i + 3000));
                size -= 3000;
                i += 3000;
            } else if(size > 0){
                Log.println(p, tag, string.substring(i, i + size));
                break;
            } else {
                break;
            }
        }
    }
}

